package com.cenntro.auth.shiro;

import java.util.List;
import java.util.Set;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.cenntro.auth.mapper.SysPermissionMapper;
import com.cenntro.auth.mapper.SysRolePermissionRefMapper;
import com.cenntro.auth.mapper.SysSooidMapper;
import com.cenntro.auth.model.dbo.SysPermissionDO;
import com.cenntro.auth.model.dbo.SysRolePermissionRefDO;
import com.cenntro.auth.model.dbo.SysSooidDO;
import com.cenntro.auth.model.dbo.SysSooidRoleRefDO;
import com.cenntro.auth.service.SysRoleService;
import com.cenntro.auth.service.SysSooidRoleRefService;
import com.cenntro.common.redis.IRedisService;
import com.cenntro.common.util.KeyUtil;
import com.cenntro.common.util.KeyUtil.keyEnum;
import com.cenntro.common.util.MessageDigestUtil;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import lombok.extern.slf4j.Slf4j;

/**
 * 验证用户登录
 * 
 * @author Administrator
 */
@Component("userRealm")
@Slf4j
public class UserRealm extends AuthorizingRealm {
	
//	@Autowired
//	private UserService userService;
//
	@Autowired
	private SysPermissionMapper permissionMapper;
	@Autowired
	private SysRolePermissionRefMapper sysRolePermissionRefMapper;
	
	@Autowired
	private SysSooidMapper userMapper;
	
	@Autowired
	private SysSooidRoleRefService sysSooidRoleRefService;
	@Autowired
	private SysRoleService sysRoleService;
	@Autowired
	private IRedisService redisService;
	
	
	
	
	public UserRealm() {
		setName("UserRealm");
		// 采用MD5加密
		setCredentialsMatcher(new HashedCredentialsMatcher("md5"));
	}

	
	//权限资源角色
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SysSooidDO user = (SysSooidDO)principals.getPrimaryPrincipal();
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		
		SysSooidRoleRefDO sysSooidRoleRef = new SysSooidRoleRefDO();
		sysSooidRoleRef.setSooid(user.getId());
		List<SysSooidRoleRefDO> refKist = sysSooidRoleRefService.selectPage(sysSooidRoleRef);  //查询角色关系
		Set<String> roles = Sets.newHashSet();
		Set<String> perms = Sets.newHashSet();
		for(SysSooidRoleRefDO ref : refKist){
			roles.add(ref.getRoleId().toString());
			
			SysRolePermissionRefDO permRef = new SysRolePermissionRefDO();
			permRef.setRoleId(ref.getRoleId());
			List<SysRolePermissionRefDO> refList = sysRolePermissionRefMapper.selectPage(permRef);  //查询角色对应权限（资源）
			for(SysRolePermissionRefDO pref : refList){
				SysPermissionDO perm = permissionMapper.selectById(pref.getPermissionId());
				if(perm != null){
					log.info("url : {}", perm.getUrl());
					perms.add(perm.getUrl());
				}
			}
		}
		info.setStringPermissions(perms);
		info.setRoles(roles);
		redisService.set(KeyUtil.keyOf(keyEnum.SHIRO_ROLES, user.getId()),Lists.newArrayList(roles));
		
		return info;
	}
	
	/**
	 * 登录验证(non-Javadoc)
	 * @see org.apache.shiro.realm.AuthenticatingRealm#doGetAuthenticationInfo(org.apache.shiro.authc.AuthenticationToken)
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken upt = (UsernamePasswordToken) token;
		char[] passwords = upt.getPassword();
		if(passwords != null){ //如果密码不是空,表示是本地登录
			String pwd = new String(passwords);
			
//			User user = this.userService.findUserByUserName(upt.getUsername());
//			SysSooidDO user = new SysSooidDO();
//			user.setUserName(upt.getUsername());
//			user.setPassword(MessageDigestUtil.MD5(pwd));
//			user.setPassword(pwd);
			SysSooidDO user = userMapper.selectOne(ImmutableMap.of("userName", upt.getUsername(), "status", 1)); // (ImmutableMap.of("userName", upt.getUsername()));
			    
			if(user == null){
				throw new AuthenticationException("登录失败， 请检查帐户和密码");
			}else {
			    if (!pwd.equals(user.getPassword()) && !MessageDigestUtil.MD5(pwd).equals(user.getPassword())){
			        throw new AuthenticationException("登录失败，  密码错误");
			    }
			}
//			if(1 == (user.getState())){ //停用
//				throw new AuthenticationException("no_status");
//			}
			SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, // 用户名
					user.getPassword(), // 密码
					ByteSource.Util.bytes(user.getId() + user.getUserName()), // salt=username+salt
					getName()); // realm name
			//this.doGetAuthorizationInfo(SecurityUtils.getSubject().getPrincipals());
			
			return info;
			//getAuthenticationInfoMethod(upt.getUsername());
		}else{ //如果密码是空，表示是远程登录，从username位置获得token
			return null;
		}
	}
	
	/** (非 Javadoc)
	* <p>Title: doClearCache</p>
	* <p>Description: </p>
	* @param principals
	* @see org.apache.shiro.realm.AuthorizingRealm#doClearCache(org.apache.shiro.subject.PrincipalCollection)
	*/
	@Override
	public void doClearCache(PrincipalCollection principals) {
	    super.doClearCache(principals);
	}
}
